/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package com.guodi.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 通用工具类
 *
 * @作者： Chill
 */
public class CommonMapUtil {

    /**
     * 字符串填充，填充右边，不会返回null
     * @入参： content 主内容字符串
     * @入参： fillStr 填充字符串
     * @入参： targetLength 目标长度
     * @出参： 如果原字符串长度比目标长度大，不做处理直接返回。如果原字符串长度比目标长度小，用fillStr重复追加到后面，再截取指定长度
     * @作者： 陈宏成
     * @日期： 2021/11/9
     */
    public static String strRightFill(String content,String fillStr ,int targetLength){
        content = StringUtils.isBlank(content)? "" : content ;
        if (content.length() >= targetLength){
            return content;
        }
        StringBuilder sb = new StringBuilder(content);
        while (sb.length() < targetLength){
            sb.append(fillStr);
        }
        return sb.substring(0, targetLength);
    }

    /**
     * @描述: 格式化字符串，用真实值替换占位符，不支持正则表达式
     * @入参: content 主要文本内容，包含了占位符，例如：这里是一个方法，{}是作者。
     * @入参: placeholder 占位符，必须保证每个占位符都相同，不然会替换失败，例如：{}
     * @入参: values 占位符对应的值，顺序要和占位符的顺序一致，会依次替换
     * @出参: 格式化后的文本
     * @作者: 陈宏成
     * @日期: 2021-03-17
     **/
    public static String strFormat(String content,String  placeholder ,String ...values){
        if (content == null || placeholder == null || values == null){
            return content;
        }
        StringBuilder stringBuilder = new StringBuilder();
        // 占位符长度
        int placeholderLength = placeholder.length();
        // 上一个占位符结束的位置
        int lastPlaceholderPosition = 0;
        for(String value : values) {
            int index = content.indexOf(placeholder,lastPlaceholderPosition);
            if (index != -1){
                stringBuilder.append(content.substring(lastPlaceholderPosition,index));
                stringBuilder.append(value);
                lastPlaceholderPosition = index + placeholderLength;
            }
        }
        // 如果后面还有内容，那就继续拼接
        stringBuilder.append(content.substring(lastPlaceholderPosition));
        return stringBuilder.toString();
    }



    /**
     * @描述:保留数字后几位小数
     * @入参: value 数字字符串
     * @出参: num 要保留的小数位数
     * @作者: 陈宏成
     * @日期: 2021-03-17
     **/
    public static String formatNumber(String value,int num){
        value = value.trim();
        // 如果没有值，那就返回空字符串
        if (!StringUtils.isNotBlank(value)){
            return "";
        }
        // 如果是整数，没有小数点，那就没必要四舍五入了
        if (!value.contains(".")){
            return value;
        }
        BigDecimal bigDecimal = new BigDecimal(value);
        bigDecimal = bigDecimal.setScale(num, RoundingMode.HALF_UP);
        return bigDecimal.toString();
    }

    /**
     * @描述:保留数字后几位小数
     * @入参: value 原数值
     * @入参: num 保留的小数位数
     * @作者: 陈宏成
     * @日期: 2021-03-17
     **/
    public static String formatNumber(double value,int num){
        BigDecimal bigDecimal = new BigDecimal(value);
        bigDecimal = bigDecimal.setScale(num, RoundingMode.HALF_UP);
        return bigDecimal.toString();
    }


    /**
     * @描述: 判断是否为0
     * @入参: value 原数值
     * @出参: true-为0，false-不为0
     * @作者: 陈宏成
     * @日期: 2021-03-18
     **/
    public static boolean isZero(double value){
        return Math.abs(value - 0) < 0.0000001 ;
    }



    /**
     * 判断字符串是否已数字开头
     * @入参： str
     * @return
     */
    public static boolean isStartWithNumber(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str.charAt(0)+"");
        if (!isNum.matches()) {
            return false;
        }
        return true;
    }

    /**
     * @描述: 去除一个list中包含的另一个list数据
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020/1/15 12:24
     **/
    public static List<String> listRem(List<String> listA, List<String> listB){
        HashSet hs1 = new HashSet(listA);
        HashSet hs2 = new HashSet(listB);
        hs1.removeAll(hs2);
        List<String> listC = new ArrayList<>();
        listC.addAll(hs1);
        return listC;
    }

    /**
     * @描述: 把所有的空字符串转化为null
     * @入参:
     * @出参:
     * @作者: 余家鑫
     * @日期: 2021/4/13 下午5:37
     */
    public static <T> T objEmptyStr2Null(T t){
        Class c = t.getClass();
        try {
            Field[] fs=c.getDeclaredFields();
            for (Field f : fs) {
                f.setAccessible(true);
                String st=f.get(t)+"";
                String str=st.replaceAll(" ", "");
                if (str.equals("")||str==null||str.equals("null")) {
                    f.set(t, null);
                }
            }
        }  catch (SecurityException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * @描述: 去除字符串中, 以某些字符结尾的数据
     * 如 输入 hahah/hahha/// 可以去结尾的/ 最终变为hahah/hahha
     * @入参:
     * @出参:
     * @作者: 余家鑫
     * @日期: 2021/4/14 下午2:44
     */
    public static String strRightTrim(String str, String endingSymbol){
        while (true){
            if(str.endsWith(endingSymbol)){
                str = str.substring(0, str.length() - endingSymbol.length());
            } else {
                break;
            }
        }

        return str;
    }
}
